from SerialDeviceControl import serialPortTool
from SerialDeviceControl import FixSerialPortTool
from EthDeviceControl import EthernetPortTool
from GpibDeviceControl import GPIBPortTool
from FileControl import fileOperate
from time import sleep
import pyvisa
import time
import sys
import json



def VoltageTest():
    global usedValue01
    global usedValue02
    global usedValue03 
       
    VoltageRange3vDone = 0
    VoltageRange30vDone = 0
    if (DMM_Mode=="V"):
        stand = 0.00
        step  = 0.1
        cycle = 116
    if (DMM_Mode=="C"):
        stand = 0.00
        step  = 0.01
        cycle = 256        
    runTime = int(cycle)/int(gain)   
    #set DMM range
    if (EnableDMM == "1") and (DMM_Mode=="C"):
        PcSendCommandToMeter("ADC") #change to Current test
        PcReceiveFromMeter(1,0)
        PcSendCommandToMeter("RATE M")  #set DMM to medium model
        PcReceiveFromMeter(1,0)
        PcSendCommandToMeter("RANGE 1") #set range to 30mA
        PcReceiveFromMeter(1,0)
    if (EnableDMM == "1") and (DMM_Mode=="V"):
        PcSendCommandToMeter("VDC") #change to voltage test
        PcReceiveFromMeter(1,0)
        PcSendCommandToMeter("RATE M")  #set DMM to medium model
        PcReceiveFromMeter(1,0)
        PcSendCommandToMeter("RANGE 1") #set range to 0.3V
        PcReceiveFromMeter(1,0)        
    if EnablePwrSource == "1":
        my_instrument.enable_output()
    for num in range(0,runTime):
        usedValue01 = usedValue01 + str(time.strftime("%Y-%m-%d_%H:%M:%S",time.localtime())) + ","
        usedValue02 = usedValue02 + str(time.strftime("%Y-%m-%d_%H:%M:%S",time.localtime())) + ","
        usedValue03 = usedValue03 + str(time.strftime("%Y-%m-%d_%H:%M:%S",time.localtime())) + ","

        #command to power source
        if EnablePwrSource=="1":
            command = "VOLT " + str(stand)
            my_instrument.gpibDeviceSend(command)
            sleep(0.01)
        getValueFromDut()     
        stand = stand + step
        sleep(0.1)
        
        #set DMM voltage range
        if (stand>=0.3) and (VoltageRange3vDone == 0):
            PcSendCommandToMeter("RANGE 2") #set range to 3V
            PcReceiveFromMeter(1,0)
            VoltageRange3vDone = 1
            
        if (stand>=3.0) and (VoltageRange30vDone == 0):
            PcSendCommandToMeter("RANGE 3") #set range to 30V
            PcReceiveFromMeter(1,0)
            VoltageRange30vDone = 1
        
    if EnablePwrSource == "1":
        my_instrument.disable_output()
    sleep(1)
       
        
def PcSendCommandToMeter(message):
    try:
        if EnableDMM == "1":
            MeterSerial.SerialPortWrite(message + '\r\n')
    except IOError as e:
        print(e)
        MeterSerial.close()
              
        
def PcReceiveFromDut():
    global strFromSeeeduino01
    global strFromSeeeduino02   
    global strFromSeeeduino03 
    global usedValue01
    global usedValue02
    global usedValue03
    strFromSeeeduino01 = ""
    strFromSeeeduino02 = ""
    strFromSeeeduino03 = ""
    #get AIN1 data
    d1,d2,d3 = get_dut_adc_data(ADC_AIN1)
    if SerialPortUnit01!="":
        usedValue01 = usedValue01 + str(d1) + ","
    if SerialPortUnit02!="":
        usedValue02 = usedValue02 + str(d2) + ","
    if SerialPortUnit03!="":
        usedValue03 = usedValue03 + str(d3) + ","
    #get AIN2 data
    d1,d2,d3 = get_dut_adc_data(ADC_AIN2)
    if SerialPortUnit01!="":
        usedValue01 = usedValue01 + str(d1) + ","
    if SerialPortUnit02!="":
        usedValue02 = usedValue02 + str(d2) + ","
    if SerialPortUnit03!="":
        usedValue03 = usedValue03 + str(d3) + ","
    #get 20mA data    
    d1,d2,d3 = get_dut_adc_data(ADC_20mA)
    if SerialPortUnit01!="":
        usedValue01 = usedValue01 + str(d1) + ","
    if SerialPortUnit02!="":
        usedValue02 = usedValue02 + str(d2) + ","
    if SerialPortUnit03!="":
        usedValue03 = usedValue03 + str(d3) + ","
    
       
def adc_setting(gain,data_type):
    # gain = 1/2
    # data_type = 0: report calibrated data
    # data_type = 1: report raw data
    gain = str(gain)
    data_type = str(data_type)
    if ((gain == "1") and (data_type== "0")):
        if SerialPortUnit01!="":
            SeeeduinoSerial01.SerialPortWrite(bytearray(ADC_Config_Gain1_ExtRef_Cal))
        if SerialPortUnit02!="":
            SeeeduinoSerial02.SerialPortWrite(bytearray(ADC_Config_Gain1_ExtRef_Cal))
        if SerialPortUnit03!="":
            SeeeduinoSerial03.SerialPortWrite(bytearray(ADC_Config_Gain1_ExtRef_Cal))
        
    if ((gain == "1") and (data_type== "1")):
        if SerialPortUnit01!="":
            SeeeduinoSerial01.SerialPortWrite(bytearray(ADC_Config_Gain1_ExtRef_Raw))
        if SerialPortUnit02!="":
            SeeeduinoSerial02.SerialPortWrite(bytearray(ADC_Config_Gain1_ExtRef_Raw))
        if SerialPortUnit03!="":
            SeeeduinoSerial03.SerialPortWrite(bytearray(ADC_Config_Gain1_ExtRef_Raw))

    if ((gain == "2") and (data_type== "0")):
        if SerialPortUnit01!="":        
            SeeeduinoSerial01.SerialPortWrite(bytearray(ADC_Config_Gain2_ExtRef_Cal))
        if SerialPortUnit02!="":            
            SeeeduinoSerial02.SerialPortWrite(bytearray(ADC_Config_Gain2_ExtRef_Cal))
        if SerialPortUnit03!="":            
            SeeeduinoSerial03.SerialPortWrite(bytearray(ADC_Config_Gain2_ExtRef_Cal))
            
    if ((gain == "2") and (data_type== "1")):
        if SerialPortUnit01!="": 
            SeeeduinoSerial01.SerialPortWrite(bytearray(ADC_Config_Gain2_ExtRef_Raw))
        if SerialPortUnit02!="":          
            SeeeduinoSerial02.SerialPortWrite(bytearray(ADC_Config_Gain2_ExtRef_Raw))  
        if SerialPortUnit03!="":          
            SeeeduinoSerial03.SerialPortWrite(bytearray(ADC_Config_Gain2_ExtRef_Raw))    
            
    if SerialPortUnit01!="": 
        SeeeduinoSerial01.SerialPortWrite(bytearray(ADC_Config_Sampling))
    if SerialPortUnit02!="":  
        SeeeduinoSerial02.SerialPortWrite(bytearray(ADC_Config_Sampling))
    if SerialPortUnit03!="": 
        SeeeduinoSerial03.SerialPortWrite(bytearray(ADC_Config_Sampling))
    sleep(0.01)
    
def get_dut_adc_data(channel):
    #channel = 3/4/5,  AIN1/AIN2/20mA  
    rcvdata_unit1 = 0
    rcvdata_unit2 = 0
    rcvdata_unit3 = 0
    if channel==ADC_AIN1:
        if SerialPortUnit01!="": 
            SeeeduinoSerial01.SerialPortWrite(bytearray(ADC_EnableReport_AIN1))
        if SerialPortUnit02!="": 
            SeeeduinoSerial02.SerialPortWrite(bytearray(ADC_EnableReport_AIN1))
        if SerialPortUnit03!="": 
            SeeeduinoSerial03.SerialPortWrite(bytearray(ADC_EnableReport_AIN1))
    if channel==ADC_AIN2:
        if SerialPortUnit01!="": 
            SeeeduinoSerial01.SerialPortWrite(bytearray(ADC_EnableReport_AIN2))
        if SerialPortUnit02!="": 
            SeeeduinoSerial02.SerialPortWrite(bytearray(ADC_EnableReport_AIN2))
        if SerialPortUnit03!="": 
            SeeeduinoSerial03.SerialPortWrite(bytearray(ADC_EnableReport_AIN2))
    if channel==ADC_20mA:
        if SerialPortUnit01!="": 
            SeeeduinoSerial01.SerialPortWrite(bytearray(ADC_EnableReport_20mA))
        if SerialPortUnit02!="": 
            SeeeduinoSerial02.SerialPortWrite(bytearray(ADC_EnableReport_20mA))
        if SerialPortUnit03!="": 
            SeeeduinoSerial03.SerialPortWrite(bytearray(ADC_EnableReport_20mA))
            
    if SerialPortUnit01!="":         
        rcvdata_unit1 = SeeeduinoSerial01.SerialPortReadADC(channel)
    if SerialPortUnit02!="":         
        rcvdata_unit2 = SeeeduinoSerial02.SerialPortReadADC(channel)
    if SerialPortUnit03!="":         
        rcvdata_unit3 = SeeeduinoSerial03.SerialPortReadADC(channel)

    if channel==ADC_AIN1:
        if SerialPortUnit01!="": 
            SeeeduinoSerial01.SerialPortWrite(bytearray(ADC_DisableReport_AIN1))
        if SerialPortUnit02!="": 
            SeeeduinoSerial02.SerialPortWrite(bytearray(ADC_DisableReport_AIN1))
        if SerialPortUnit03!="": 
            SeeeduinoSerial03.SerialPortWrite(bytearray(ADC_DisableReport_AIN1))
    if channel==ADC_AIN2:
        if SerialPortUnit01!="": 
            SeeeduinoSerial01.SerialPortWrite(bytearray(ADC_DisableReport_AIN2))
        if SerialPortUnit02!="": 
            SeeeduinoSerial02.SerialPortWrite(bytearray(ADC_DisableReport_AIN2))
        if SerialPortUnit03!="": 
            SeeeduinoSerial03.SerialPortWrite(bytearray(ADC_DisableReport_AIN2))
    if channel==ADC_20mA:
        if SerialPortUnit01!="": 
            SeeeduinoSerial01.SerialPortWrite(bytearray(ADC_DisableReport_20mA))
        if SerialPortUnit02!="": 
            SeeeduinoSerial02.SerialPortWrite(bytearray(ADC_DisableReport_20mA))
        if SerialPortUnit03!="": 
            SeeeduinoSerial03.SerialPortWrite(bytearray(ADC_DisableReport_20mA))
        
    return rcvdata_unit1,rcvdata_unit2,rcvdata_unit3  
        
        

def PcReceiveFromMeter(ntime,usedValue):
    global strFromMultiMeter
    global usedValue01
    global usedValue02
    global usedValue03
    strFromMultiMeter = ""
    n = 0
    while(n<ntime):
        if EnableDMM == "1":
            line = MeterSerial.SerialPortReadLine()
        if line and (usedValue==1):
#            print(time.strftime("%H:%M:%S", time.localtime()) + " PC <- Seeeduino: " + line)
            strFromMultiMeter = strFromMultiMeter + line
#            usedValue01 = usedValue01 + line[1:(line.find("E")+1)] + ","
            usedValue01 = usedValue01 + line[1:-2] + ","
            usedValue02 = usedValue01
            usedValue03 = usedValue01
        sleep(0.001)
        n = n+1        


def getValueFromDut():
    global gain    
    global logName01
    global logName02
    global logName03
    global usedValue01
    global usedValue02
    global usedValue03
    
    #get data from fluke DMM
    if EnableDMM == "1":
        PcSendCommandToMeter("MEAS?")
        PcReceiveFromMeter(1,1)
    else:
        usedValue01 = usedValue01 + ","
        usedValue02 = usedValue02 + ","
        usedValue03 = usedValue03 + ","        
   
    #get IoT Expansion Analog data
    adc_setting(gain,1)     #get adc Raw data
    PcReceiveFromDut();     
    adc_setting(gain,0)     #get adc calibrated data
    PcReceiveFromDut();
    
    #write data to log file  
    if Unit1NeedToWrite == "1":
        logFile_01.fileWrite(usedValue01 + "\n")
    if Unit2NeedToWrite == "1":
        logFile_02.fileWrite(usedValue02 + "\n")
    if Unit3NeedToWrite == "1":
        logFile_03.fileWrite(usedValue03 + "\n")
 
    print(str(DutNo1) + " data: " + usedValue01)
    print(str(DutNo2) + " data: " + usedValue02)
    print(str(DutNo3) + " data: " + usedValue03)
    usedValue01 = ""
    usedValue02 = ""
    usedValue03 = ""


#--------------------------------------MAIN-----------------------#
#ADC configure Command
ADC_Config_Gain1_ExtRef_Raw = [0xF0,0x5F,0x00,0x31,0x01,0xF7]       #MCU ADC Gain = 1, External REF, report raw to host
ADC_Config_Gain1_ExtRef_Cal = [0xF0,0x5F,0x00,0x31,0x00,0xF7]       #MCU ADC Gain = 1, External REF, report calibrate value to host
ADC_Config_Gain2_ExtRef_Raw = [0xF0,0x5F,0x00,0x32,0x01,0xF7]       #MCU ADC Gain = 2, External REF, report raw to host
ADC_Config_Gain2_ExtRef_Cal = [0xF0,0x5F,0x00,0x32,0x00,0xF7]       #MCU ADC Gain = 2, External REF, report calibrate value to host
ADC_Config_Sampling         = [0xF0,0x7A,0x64,0x00,0xF7]            #Set ADC report sampling is: 100ms
ADC_EnableReport_AIN1       = [0xC3,0x01]                           #Enable AIN1 auto report
ADC_EnableReport_AIN2       = [0xC4,0x01]                           #Enable AIN2 auto report
ADC_EnableReport_20mA       = [0xC5,0x01]                           #Enable 20mA auto report
ADC_DisableReport_AIN1      = [0xC3,0x00]                           #Disable AIN1 auto report
ADC_DisableReport_AIN2      = [0xC4,0x00]                           #Disable AIN2 auto report
ADC_DisableReport_20mA      = [0xC5,0x00]                           #Disable 20mA auto report

type   = str(sys.argv[1])
gain   = str(sys.argv[2])
tmp    = str(sys.argv[3])
folder = str(sys.argv[4])

with open("config.json",'r') as f:
    configure = json.load(f)
    
EnablePrintDebugInfo  = configure["EnablePrintDebugInfo"]
SerialPortUnit01      = configure["DutNo1_SerialPort"]
SerialPortUnit02      = configure["DutNo2_SerialPort"]
SerialPortUnit03      = configure["DUTNo3_SerialPort"]
PwrSourceGPIBAddress  = configure["PwrSourceGPIBAddr"]
EnablePwrSource       = configure["EnablePwrSource"]
EnableDMM             = configure["EnableDMM"]
DutNo1                = configure["DutNo1#"]
DutNo2                = configure["DutNo2#"]
DutNo3                = configure["DutNo3#"]
DMM_Mode              = configure["DMM_Mode"]   #1:voltage, 2: current

ADC_AIN1    = 3
ADC_AIN2    = 4
ADC_20mA    = 5

#print SerialPortUnit01
#print SerialPortUnit02
#print SerialPortUnit03

#using when only need 1 or 2 dut need write log
Unit1NeedToWrite = configure["DutNo1_WriteLogEnable"]
Unit2NeedToWrite = configure["DutNo2_WriteLogEnable"]
Unit3NeedToWrite = configure["DutNo3_WriteLogEnable"]


SeeeduinoSerial01 = None
SeeeduinoSerial02 = None
SeeeduinoSerial03 = None
MultiMeter_SerialPort = None

strFromSeeeduino01 =""
strFromSeeeduino02 =""
strFromSeeeduino03 =""
strFromMultiMeter = ""

usedValue01 = ""
usedValue02 = ""
usedValue03 = ""

if (folder == "i") or (folder == "I"):
    filePath = ".././ref_1.0/"
    
if (folder == "e") or (folder == "E"):
    filePath = ".././ref_2.5/"    

#init the Aglient Power source
if EnablePwrSource=="1":
    my_instrument = GPIBPortTool(PwrSourceGPIBAddress,EnablePrintDebugInfo)
    my_instrument.initDevice()
    my_instrument.current_limit(0.5)    #output current max 0.5A


#init the fluke DMM
if EnableDMM=="1":
    MeterSerial = serialPortTool('USB VID:PID=067B:2303',EnablePrintDebugInfo)
    MeterSerial.find_SerialPort()
    MeterSerial.SerialPortopen()

#init the DUT port
if SerialPortUnit01!="":
    SeeeduinoSerial01 = FixSerialPortTool(SerialPortUnit01,EnablePrintDebugInfo)
    SeeeduinoSerial01.SerialPortopen()
if SerialPortUnit02!="":
    SeeeduinoSerial02 = FixSerialPortTool(SerialPortUnit02,EnablePrintDebugInfo)
    SeeeduinoSerial02.SerialPortopen()
if SerialPortUnit03!="":
    SeeeduinoSerial03 = FixSerialPortTool(SerialPortUnit03,EnablePrintDebugInfo)
    SeeeduinoSerial03.SerialPortopen()



currentTime = time.strftime("T%Y%m%d-%H%M%S",time.localtime())
logTitle = "Time,MeterValue,AIN1(Raw),AIN2(Raw),20mA(Raw),AIN1(Cal),AIN2(Cal),20mA(Cal)"

if Unit1NeedToWrite == "1":
    logName01 = currentTime.strip("\r\n") + "_#" + str(DutNo1) + "_gain" + str(gain) + "_tmp" + str(tmp) + "_" + DMM_Mode + ".txt"
    logFile_01 = fileOperate(filePath,logName01,EnablePrintDebugInfo)
    logFile_01.creatFileObjectWrite()
    logFile_01.fileWrite(logTitle + "\n")   #write Title to log file
if Unit2NeedToWrite == "1":
    logName02 = currentTime.strip("\r\n") + "_#" + str(DutNo2) + "_gain" + str(gain) + "_tmp" + str(tmp) + "_" + DMM_Mode + ".txt"
    logFile_02 = fileOperate(filePath,logName02,EnablePrintDebugInfo)
    logFile_02.creatFileObjectWrite()
    logFile_02.fileWrite(logTitle + "\n")   #write Title to log file
if Unit3NeedToWrite == "1":
    logName03 = currentTime.strip("\r\n") + "_#" + str(DutNo3) + "_gain" + str(gain) + "_tmp" + str(tmp) + "_" + DMM_Mode + ".txt"
    logFile_03 = fileOperate(filePath,logName03,EnablePrintDebugInfo)
    logFile_03.creatFileObjectWrite()
    logFile_03.fileWrite(logTitle + "\n")   #write Title to log file


VoltageTest()

if SerialPortUnit01!="":
    SeeeduinoSerial01.SerialPortClose()
if SerialPortUnit02!="":
    SeeeduinoSerial02.SerialPortClose()
if SerialPortUnit03!="":
    SeeeduinoSerial03.SerialPortClose()
if EnableDMM == "1":
    MeterSerial.SerialPortClose()
if Unit1NeedToWrite == "1":
    logFile_01.fileClose()
if Unit2NeedToWrite == "1":
    logFile_02.fileClose()
if Unit3NeedToWrite == "1":
    logFile_03.fileClose()

    
   






















